<?php
/*
	Author: John Joseph Bachir (http://blog.johnjosephbachir.org/)
	License: GPL 2

	This is a general XHTML tag generation library.

	For each XHTML 1.0 Transitional tag, there is a 
	corresponding function composed of an underscore 
	followed by the tag.

	The first parameter of the function is an array containing
	the tag's attributes, and the second parameter is the tag's body.
	The second parameter is required for regular tags and of course
	not needed for self-closing tags. The first parameter is always
	optional.

	All of the functions return tag that they generate as a text
	string. The encapsulating code is responsible for concatenating
	and echoing the results.

		// generates: <br />
		_br();

		// generates <p>Hello, World.</p>
		_p('Hello, World.');

		// generates: <p class="foo" id="greeting">Hello, World.</p>
		_p(array('class'=>'foo', 'id'=>'greeting'), 'Hello, World.');

		// generates:
		// <ol class="foo" id="mylist">
		// 	<li>thing one</li>
		// 	<li><code>thing two</code></li>
		// </ul>
		_ol(array('class'=>'foo', 'id'=>'mylist'),
			_li('thing one') .
			_li(_code('thing two')) .
		);

	There is also a simple convenience function for escaping strings
	for output to html, e().

		// note: this is just a simple example, user input should almost always
		// 	be filtered before being output to a device
		_p(array(class="foo" id="results"),
			'You entered: ' .
			e($_POST['useroptions'])
		);

*/

// XHTML 1.0 Transitional tags
$tags = array('a', 'abbr', 'acronym', 'address', 'applet', 'area', 'b', 'bdo', 'big', 'blockquote', 'body', 'button', 'caption', 'cite', 'code', 'colgroup', 'dd', 'del', 'dfn', 'div', 'dl', 'DOCTYPE', 'dt', 'em', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'i', 'iframe', 'ins', 'kbd', 'label', 'legend', 'li', 'link', 'map', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'p', 'pre', 'q', 'samp', 'script', 'select', 'small', 'span', 'strong', 'style', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'tt', 'ul', 'var');

// XHTML 1.0 Transitional self-closing tags
$tags_sc = array('base', 'br', 'col', 'frame', 'hr', 'input', 'img', 'meta', 'param');

function construct_attributes($attributes){
	$attributestring = '';
	if (false !== $attributes){
		foreach($attributes as $name => $value){
			$attributestring .= " $name=\"$value\"";
		}
	}
	return $attributestring;
}

function construct_tag($tag, $attributestring, $sc, $body=false){
	$tagstring = '<' . $tag . $attributestring;
	$tagstring.=
		$sc ?
			' />' :
			'>' . $body . '</'.$tag.'>';
	return $tagstring;
}

function tag($tag, $body, $attributes=false){
	return construct_tag($tag, construct_attributes($attributes), false, $body);
}

function tag_sc($tag, $attributes=false){
	return construct_tag($tag, construct_attributes($attributes), true);
}

function create_tag_function($tag, $sc){
	if (!$sc)
		return "
			function _$tag(){ //attributes, body
				if (2==func_num_args()){ " . '
					$body = func_get_arg(1);
					$attributes = func_get_arg(0); ' . " 
					return tag('$tag', " .'$body, $attributes'. ");
				}
				else{ " . '
					$body = func_get_arg(0); ' . "
					return tag('$tag', " .'$body, false'. ");
				}
			}
		";
	else
		return "
			function _$tag(){ //attributes, body
				if (1==func_num_args()){ " . '
					$attributes = func_get_arg(0); ' . "
					return tag_sc('$tag', " .'$attributes'. ");
				}
				else{
					return tag_sc('$tag', " .'false'. ");
				}
			}
		";
}

$code = '';

foreach($tags as $tag){
	$code .= create_tag_function($tag, false);
}

foreach($tags_sc as $tag){
	$code .= create_tag_function($tag, true);
}

// uncomment this to take a look at all the functions being generated
//	echo '<pre>' . $code . '</pre>'; die;

eval($code);

function e($string){
	return htmlentities($string, ENT_QUOTES, 'UTF-8');
}

?>
